import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix , precision_score, recall_score, f1_score

# 读取 Excel 文件
excel_file = pd.ExcelFile('信用卡精准营销模型.xlsx')

# 获取所有表名
sheet_name = excel_file.sheet_names

# 获取指定工作表中的数据
df = excel_file.parse('Sheet1')

# 查看数据的基本信息
print('数据基本信息：')
df.info()

# 查看数据集行数和列数
rows, columns = df.shape

if rows < 100 and columns < 20:
    # 短表数据（行数少于100且列数少于20）查看全量数据信息
    print('数据全部内容信息：')
    print(df.to_csv(sep='\t', na_rep='nan'))
else:
    # 长表数据查看数据前几行信息
    print('数据前几行内容信息：')
    print(df.head().to_csv(sep='\t', na_rep='nan'))

# 数据处理：检查异常值（以月收入为例，假设月收入在 1000 到 100000 之外为异常值）
df = df[(df['月收入（元）'] >= 1000) & (df['月收入（元）'] <= 100000)]

# 数据分析：查看各特征与响应的相关性
correlation = df.corr()['响应'].drop('响应')
print('各特征与响应的相关性：')
print(correlation)

# 建模：准备特征和目标变量
X = df.drop('响应', axis=1)
y = df['响应']

# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 创建逻辑回归模型并训练
model = LogisticRegression()
model.fit(X_train, y_train)

# 模型评价：在测试集上进行预测
y_pred = model.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
precision = precision_score(y_test, y_pred)
recall = recall_score(y_test, y_pred)
f1 = f1_score(y_test, y_pred)

print('模型准确率：', accuracy)
print('模型精确率：', precision)
print('模型召回率：', recall)
print('模型F1分数：', f1)

# 查看分类报告
print('分类报告：')
print(classification_report(y_test, y_pred))

# 查看混淆矩阵
conf_matrix = confusion_matrix(y_test, y_pred)
print('混淆矩阵：')
print(conf_matrix)

# 设置图片清晰度
plt.rcParams['figure.dpi'] = 300

# 设置中文字体
plt.rcParams['font.sans-serif'] = ['WenQuanYi Zen Hei']

# 可视化：绘制相关性热力图
plt.figure(figsize=(8, 6))
sns.heatmap(df.corr(), annot=True, cmap='coolwarm', fmt=".2f")
plt.title('特征相关性热力图')
plt.show()

# 绘制混淆矩阵热力图
plt.figure(figsize=(6, 4))
sns.heatmap(conf_matrix, annot=True, fmt='d', cmap='Blues')
plt.xlabel('预测值')
plt.xticks(rotation=45)
plt.ylabel('真实值')
plt.title('混淆矩阵热力图')
plt.show()